package ui;

import java.io.*;
import java.awt.TextArea;
import java.awt.Font;

/**
 * This class combines the data model and the view to inspect and edit a series
 * of x-y value pairs. The model stores both a raw text representation and the
 * same data converted into an array of points. The raw text is stored because
 * the user may embed comments into his input. These comments would get lost if
 * only the numeric point data was stored.
 * 
 * @version 1.0
 * @author Hans U. Gerber (<a
 *         href="mailto:gerber@ifh.ee.ethz.ch">gerber@ifh.ee.ethz.ch</a>)
 */
public class PointsUI extends TextArea implements Validatable {
	private String label;
	private RealPoint[] data;
	private String rawText;

	public PointsUI(String label, String rawText) {
		super();
		setFont(new Font("Courier", Font.PLAIN, 10));
		this.label = label;
		this.rawText = rawText;
		this.data = read(rawText);
		display();
	}

	public String getLabel() {
		return label;
	}

	public void display() {
		setText(rawText);
	}

	public RealPoint[] get() {
		return data;
	}

	/**
	 * Checks if the contents of the edit field are valid, i.e. the user entered
	 * at least 10 x-y pairs.
	 * 
	 * @return <code>null</code> if valid, an error message otherwise.
	 */
	public String check() {
		RealPoint[] temp = read(getText());
		boolean ok = (temp != null && temp.length >= 10);
		if (ok) {
			return null;
		} else {
			return "\"" + label
					+ "\" must contain at least 10 x-y-value pairs.";
		}
	}

	/**
	 * Copies the raw text and the x-y values (read from the same raw text) from
	 * the edit field into the model. This method assumes that the contents of
	 * the field have already been validated.
	 */
	public void accept() {
		rawText = getText();
		data = read(rawText);
	}

	static final int MAX_NR_OF_FITNESS_CASES = 100;

	/**
	 * Decodes the contents of the edit field into a series of x-y value pairs.<br>
	 * Note that the strean tokenizer used here does not understand numbers with
	 * an exponent (like 1.23E+3).
	 * 
	 * @return an array of x-y points
	 */
	private RealPoint[] read(String s) {
		StringBufferInputStream stream = new StringBufferInputStream(s);
		StreamTokenizer tokenizer = new StreamTokenizer(stream);
		RealPoint[] temp = new RealPoint[MAX_NR_OF_FITNESS_CASES];
		int count = 0;
		try {
			int token;
			do {
				double x;
				double y;
				token = tokenizer.nextToken();
				if (token == StreamTokenizer.TT_NUMBER) {
					x = tokenizer.nval;
					token = tokenizer.nextToken();
					if (token == StreamTokenizer.TT_NUMBER) {
						y = tokenizer.nval;
						temp[count] = new RealPoint(x, y);
						count++;
					}
				}
			} while (count < MAX_NR_OF_FITNESS_CASES
					&& token != StreamTokenizer.TT_EOF);
		} catch (Exception e) {
			;
		}
		RealPoint[] result = new RealPoint[count];
		System.arraycopy(temp, 0, result, 0, count);
		return result;
	}

}
